import java.lang.reflect.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author omenkk7
 * @description   生成mapper实例的工厂
 * @create 2025/9/10
 */
public class MysqlSessionFactory {


    private static final String JDBCURL = "jdbc:mysql://localhost:3306/mybatis_db";
    private static final String DBUSER = "root";
    private static final String PASSWORD = "13670389479LQH";
    /**
     *
     *
     * 获取动态代理对象，并且注册拦截逻辑
     * 为什么采用工厂的类加载器
     *
     * @param mapper
     * @return
     * @param <T>
     */
    public <T> T getMapper(Class<T> mapper){
    return (T)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{mapper}, new MySqlInvocationHandler());
    }


    static class MySqlInvocationHandler implements InvocationHandler{


        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            String methodName = method.getName();
            //如果是查询方法
            if(methodName.startsWith("select")){
                 return invokeSelect(proxy,method,args);
            }

            return null;
        }


        public Object invokeSelect(Object proxy, Method method, Object[] args){
            //创建sql语句
    String sql=createSelectSQL(method);
            System.out.println(sql);

            //下面为jdbc操作
            try (Connection conn = DriverManager.getConnection(JDBCURL, DBUSER, PASSWORD);
                 PreparedStatement statement = conn.prepareStatement(sql)) {
                for (int i = 0; i < args.length; i++) {
                    Object arg = args[i];
                    if (arg instanceof Integer) {
                        statement.setInt(i + 1, (int) arg);
                    } else if (arg instanceof String) {
                        statement.setString(i + 1, arg.toString());
                    }
                }
                ResultSet rs = statement.executeQuery();
                if (rs.next()) {
                    return parseResult(rs, method.getReturnType());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;



        }

        private Object parseResult(ResultSet rs, Class<?> returnType) throws Exception {
            Constructor<?> constructor = returnType.getConstructor();
            Object result = constructor.newInstance();
            Field[] declaredFields = returnType.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                Object column = null;
                String name = declaredField.getName();
                if (declaredField.getType() == String.class) {
                    column = rs.getString(name);
                } else if (declaredField.getType() == Integer.class) {
                    column = rs.getInt(name);
                }
                declaredField.setAccessible(true);
                declaredField.set(result, column);
            }
            return result;
        }

        private String createSelectSQL(Method method) {

            StringBuilder sql=new StringBuilder();
            sql.append("select ");
            List<String> fieldList =getFieldList(method.getReturnType());
            //添加参数名
            sql.append(String.join(",",fieldList));
            //from
            sql.append(" from ");
            //添加表名
           String tableName= getTableName(method.getReturnType());
           sql.append(tableName);
           //添加参数信息
            sql.append(" where ");
            String where=getWhere(method);
            sql.append(where);
            return sql.toString();


        }

        private String getWhere(Method method) {
            //获取条件
            String  condition = Arrays.stream(method.getParameters()).map(param -> {
                Param annotation = param.getAnnotation(Param.class);
                String value = annotation.value();
                return value + " = ?";
            }).collect(Collectors.joining(" and "));
                return condition;
        }

        /**
         * 根据方法返回值获取表名
         * @param returnType
         * @return
         */
        private String  getTableName(Class<?> returnType) {
            Table table = returnType.getAnnotation(Table.class);
            return table.tableName();
        }

        /**
         * 获取方法的参数的类名
         * @param returnType
         * @return
         */
        private List<String> getFieldList(Class<?> returnType) {
            Field[] declaredFields = returnType.getDeclaredFields();
         return  Arrays.stream(declaredFields).map(Field::getName).toList();
        }
    }
}
